/**
 * 
 */
package com.alstudio.module.voip;

import org.pjsip.pjsua2.ALVoipWorkingStateCallback;
import org.pjsip.pjsua2.app.ALVoipManager;
import org.pjsip.pjsua2.app.PostToRemoteUserData;

import android.content.Context;

import com.alstudio.event.ALEventDeliver;
import com.alstudio.module.BaseModule;
import com.alstudio.module.ModuleEvent;
import com.alstudio.module.ModuleEventType;
import com.alstudio.module.xmpp.protocol.xmpp.packact.ALMessage;
import com.alstudio.utils.log.ALLog;

/**
 * @author alonso lee
 * 
 */
public class ALVoipModuleManager extends BaseModule implements
		ALVoipWorkingStateCallback {

	public static final String DEFAULT_RTP_SERVER_IP = "116.254.203.66";
	public static final int DEFAULT_RTP_SERVER_PORT = 5552;

	private String successIp;
	private int successPort;

	private static ALVoipModuleManager defaultManager;
	// 实用编码
	private String usingCodec = null;

	/**
	 * 获取全局的voip模块管理器
	 * 
	 * @return 全局的voip模块管理器
	 */
	private static ALVoipModuleManager getDefaultALVoipModuleManager() {
		if (defaultManager == null) {
			defaultManager = new ALVoipModuleManager();
		}
		return defaultManager;
	}

	/**
	 * 
	 */
	public ALVoipModuleManager() {
		// TODO Auto-generated constructor stub
		setHandleEvent(ALVoipEvent.class);
		ALVoipManager.setAlVoipWorkingStateCallback(this);
		// registerModule(null);
	}

	/**
	 * @param usingCodec
	 *            the usingCodec to set
	 */
	public void setUsingCodec(String usingCodec) {
		this.usingCodec = usingCodec;
	}

	/**
	 * @return the usingCodec
	 */
	public String getUsingCodec() {
		return usingCodec;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.alstudio.module.BaseModule#registerModule(java.lang.Object)
	 */
	@Override
	public void registerModule(Context context) {
		// TODO Auto-generated method stub
		ALVoipManager.registerVoipModule();
		// 通知模块管理器模块已经正确开启
		ModuleEvent event = newModuleEvent();
		event.setModuleEventType(ModuleEventType.MODULE_START_SUCCESS);
		postModuleEvent(event);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.alstudio.module.BaseModule#unregisterModule(java.lang.Object)
	 */
	@Override
	public void unregisterModule(Context context) {
		// TODO Auto-generated method stub
		ALVoipManager.unRegisterVoipModule();
		ModuleEvent event = newModuleEvent();
		event.setModuleEventType(ModuleEventType.MODULE_STOP);
		postModuleEvent(event);

	}

	public String getSuccessIp() {
		return successIp;
	}

	public int getSuccessPort() {
		return successPort;
	}
	
	public void reSendAudio(){
		ALVoipManager.startStream(successIp, successPort, usingCodec);
	}

	/**
	 * 向rtp服务器上传本地内网ip地址，网络类型、本地udp端口、应用程序登陆的账号（纯id）
	 * 
	 * @param data
	 *            由应用程序登陆的账号（纯id）&本地内网ip地址&本地udp端口&网络类型拼装的数据包。如
	 *            '&200281&192.168.1.121&4000&wifi'
	 * @param serverIp
	 *            rtp服务器地址
	 * @param serverPort
	 *            rtp服务器端口
	 */
	public void postUdpDataToServer(ALPostToRtpServerData data) {
		ALVoipManager.postUdpDataToServer(data);
	}

	/**
	 * 与通话用户进行打洞工作。根据msg中带有的nat、lan、turn地址，发送的数据位当前通话的sessionid
	 * 
	 * @param msg
	 *            从此对象可取得通话对方的nat、lan、turn地址。得到sessionid，传送给对方
	 */
	public void postUdpDataToRemoteUser(ALMessage msg) {
		ALVoipManager
				.postUdpDataToRemoteUser(almessageToPostToRemoteUserData(msg));
	}

	/**
	 * 传送语音到指定ip、端口
	 * 
	 * @param ip
	 *            待传输语音的ip
	 * @param port
	 *            待传输语音的端口
	 */
	public void startStream(String ip, int port, String codec) {
		ALVoipManager.startStream(ip, port, codec);
	}

	/**
	 * 停止发送语音
	 */
	public void stopStream() {
		ALVoipManager.stopStream();
	}

	/**
	 * 获取传递给rtp服务器的数据
	 * 
	 * @param userId
	 *            当前登录的userid（纯id）
	 * @param lanIp
	 *            当前wifi内网地址
	 * @param localPort
	 *            当前端口
	 * @param networkType
	 *            当前网络类型
	 * @return
	 */
	public static ALPostToRtpServerData getPostToRtpServerData(String userId,
			String lanIp, int localPort, String networkType, String rtpIp,
			int rtpServerPort) {

		ALPostToRtpServerData data = new ALPostToRtpServerData();

		data.setUserId(userId);
		data.setLocalIp(lanIp);
		data.setLocalPort(localPort);
		data.setNetwokType(networkType);
		data.setRtpServerIp(rtpIp);
		data.setRtpServerPort(rtpServerPort);

		return data;
	}

	/**
	 * 将ALMessage类数据转为PostToRemoteUserData
	 * 
	 * @param msg
	 * @return
	 */
	public static PostToRemoteUserData almessageToPostToRemoteUserData(
			ALMessage msg) {
		if (msg != null) {
			PostToRemoteUserData data = new PostToRemoteUserData();
			// 内网地址
			data.setLanIp(msg.getLanIp());
			// 内网端口
			data.setLanPort(msg.getLanPort());
			// 外网地址
			data.setNatIp(msg.getNatIp());
			// 外网端口
			data.setNatPort(msg.getNatPort());
			// 中转服务器地址
			data.setTransferIp(msg.getTransferIp());
			// 中转服务器端口
			data.setTransferPort(msg.getTransferPort());
			// 当前会话id
			data.setVoipSession(msg.getVoipSession());
			return data;
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.pjsip.pjsua2.ALVoipWorkingStateCallback#onNegotiateFail(java.lang
	 * .String, int)
	 */
	@Override
	public void onNegotiateFail(String ip, int remote_port) {
		// TODO Auto-generated method stub
		ALLog.e("与地址 " + ip + " 端口 " + " 协商失败");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.pjsip.pjsua2.ALVoipWorkingStateCallback#onNegotiateSuccess(java.lang
	 * .String, int)
	 */
	@Override
	public void onNegotiateSuccess(String ip, int remote_port) {
		// TODO Auto-generated method stub
		ALLog.e("与地址 " + ip + " 端口 " + " 协商成功!开始传输语音");
		ALVoipManager.startStream(ip, remote_port, usingCodec);
		successIp = ip;
		successPort = remote_port;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.pjsip.pjsua2.ALVoipWorkingStateCallback#onPostDataToRtpResult(int)
	 */
	@Override
	public void onPostDataToRtpResult(int result) {
		// TODO Auto-generated method stub
		ALVoipEvent event = new ALVoipEvent();

		if (result != -1) {
			// 与rtp服务器协商成功
			event.setEventType(ALVoipEventType.ALVOIP_EVENT_POST_DATA_TO_RTP_SERVER_SUCCESS);
		} else {
			event.setEventType(ALVoipEventType.ALVOIP_EVENT_POST_DATA_TO_RTP_SERVER_FAIL);
			ALLog.e("与rtp服务器协商失败");
		}
		// 向UI抛出事件
		ALEventDeliver.getDefaultAlEventDeliver().postALEvent(event);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.alstudio.module.BaseModule#onModuleManagerEvent(com.alstudio.module
	 * .BaseModule)
	 */
	@Override
	public void onModuleManagerEvent(Object event) {
		// TODO Auto-generated method stub
		invokeVoipModuleEvent(event);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.alstudio.module.BaseModule#newModuleEvent()
	 */
	@Override
	public ModuleEvent newModuleEvent() {
		ModuleEvent event = new ModuleEvent(this);
		return event;
	}

	/**
	 * 开始处理事件
	 * 
	 * @param event
	 */
	private void invokeVoipModuleEvent(Object event) {
		ALVoipEvent e = (ALVoipEvent) event;
		Object data = e.getData();
		ALLog.i(this.getClass().getSimpleName() + " 正在处理事件 " + e.getEventType());
		switch (e.getEventType()) {
		case ALVOIP_EVENT_POST_DATA_TO_REMOTE_USER:
			ALVoipManager.postUdpDataToRemoteUser((PostToRemoteUserData) data);
			break;
		case ALVOIP_EVENT_POST_DATA_TO_RTP_SERVER:
			postUdpDataToServer((ALPostToRtpServerData) data);
			break;
		case ALVOIP_EVENT_START_STREAM_TO_REMOTE_USER:
			// 传输语音
			break;
		case ALVOIP_EVENT_STOP_STREAM_TO_REMOTE_USER:
			// 停止传输
			ALVoipManager.stopStream();
			break;
		case ALVOIP_EVENT_RESTART_STREAM:
			reSendAudio();
			break;
		default:
			ALLog.w("无法处理事件 " + e.getEventType());
			break;

		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.alstudio.module.BaseModule#setHandleEvent(java.lang.Object)
	 */
	@Override
	public void setHandleEvent(Class<?> event) {
		// TODO Auto-generated method stub
		this.handleEvent = event;
	}
}
